﻿using Adnc.Application.Shared.Services;
using Adnc.Infra.Helper;
using Adnc.Infra.IRepositories;
using Adnc.Shared.RpcServices.Rtos.Usr;
using Adnc.Shared.RpcServices.Services;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Net;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using WYT.Sys.Application.Contracts.Dtos.Coupon;
using WYT.Sys.Application.Contracts.Dtos.Edu;
using WYT.Sys.Application.Contracts.Services;
using WYT.Sys.Repository.Entities;

namespace WYT.Sys.Application.Services
{
    /// <summary>
    /// 
    /// </summary>
    public class EduAppService : AbstractAppService, IEduAppService
    {
        private readonly IEfRepository<EduGroup> _eduGroupEfRepository;

        private readonly IEfRepository<EduCourse> _eduCourseEfRepository;

        private readonly IEfRepository<EduPhase> _eduPhaseEfRepository;

        private readonly IEfRepository<EduLesson> _eduLessonEfRepository;

        private readonly IEfRepository<EduRecords> _eduRecordsEfRepository;

        private readonly IEfRepository<EduTeacher> _eduTeacherEfRepository;

        private readonly IUserRpcService _userRpcService;

        public EduAppService(
        IEfRepository<EduGroup> eduGroupEfRepository
        , IEfRepository<EduCourse> eduCourseEfRepository
        , IEfRepository<EduPhase> eduPhaseEfRepository
        , IEfRepository<EduLesson> eduLessonEfRepository
        , IEfRepository<EduRecords> eduRecordsEfRepository
        , IEfRepository<EduTeacher> eduTeacherEfRepository
        , IUserRpcService userRpcService)
        {
            _eduCourseEfRepository = eduCourseEfRepository;
            _eduGroupEfRepository = eduGroupEfRepository;
            _eduLessonEfRepository = eduLessonEfRepository;
            _eduPhaseEfRepository = eduPhaseEfRepository;
            _eduRecordsEfRepository = eduRecordsEfRepository;
            _eduTeacherEfRepository = eduTeacherEfRepository;
            _userRpcService = userRpcService;
        }

        /// <summary>
        /// 获取课时列表
        /// </summary>
        /// <param name="courseId"></param>
        /// <param name="phaseId"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<EduLessonDto>>> GetEduLessonByGroupId(long courseId,long phaseId)
        {
            var expreession = ExpressionCreator.New<EduLesson>()
                .AndIf(phaseId > 0,x => x.Phase == phaseId)
                .And(x => x.Course == courseId && x.Deleted == false);
            var lessons = _eduLessonEfRepository.Where(expreession).OrderBy(x => x.Id).ToList();
            var lessonIds = lessons.Select(x => x.Id).ToList();
            string sql = @$"SELECT er.Lesson, count(DISTINCT er.`User` ) AS Count FROM sys_EduRecords er WHERE er.Lesson in @ids GROUP BY er.Lesson";
            var data = await _eduRecordsEfRepository.QueryAsync<LessonStatisticsDto>(sql, new { ids = lessonIds });
            var result = lessons.Select(x => new EduLessonDto
            {
                Id = x.Id,
                Course = x.Course,
                Phase = x.Phase,
                Address = x.Address,
                CreateDate = x.CreateDate,
                LessonImg = x.LessonImg,
                Title = x.Title,
                Type = x.Type,
                LearnCount = (data.FirstOrDefault(c => c.Lesson == x.Id)?.Count) ?? 0,
            }).ToList();

            return result;
        }

        /// <summary>
        /// 获取分组
        /// </summary>
        /// <param name="type"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<EduGroupListDto>>> GetGroupList(int type)
        {
            var groups = await _eduGroupEfRepository.Where(x => x.Type == type && x.Deleted == false)
                .OrderBy(x => x.Sort)
                .ToListAsync();
            var groupIds = groups.Select(x => x.Id).ToList();
            var Courses = _eduCourseEfRepository.Where(x => groupIds.Contains(x.Group) && x.Deleted == false).ToList();

            string sql = @$"SELECT er.Course, count(DISTINCT er.`User` ) AS count FROM sys_EduRecords er WHERE er.Group in @ids GROUP BY er.Course";
            var numdata = await _eduRecordsEfRepository.QueryAsync(sql, new { ids = groupIds });

            var result = groups.Select(x => new EduGroupListDto
            {
                Id = x.Id,
                GroupName = x.GroupName,
                EduCourses = Courses.FindAll(c => c.Group == x.Id).Select(x => new EduCourseDto {
                    Id = x.Id,
                    Title = x.Title,
                    Desc = x.Wikipedia,
                    SurfacePlot = x.ImageAddress,
                    Grade = x.Grade,
                    Records = (numdata.FirstOrDefault(c => c.Course == x.Id)?.count) ?? 0,
                }).ToList(),
            }).ToList();
            return result;
        }

        /// <summary>
        /// 获取课程详情
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<EduGroupDetailDto>> GetCourseDetail(long input)
        {
            var data = await _eduCourseEfRepository.FindAsync(input);
            if (data == null)
                return Problem(HttpStatusCode.NotFound, "");
            var count =await _eduRecordsEfRepository.CountAsync(x => x.Course == input);
            return new EduGroupDetailDto {
                Id = data.Id,
                Title = data.Title,
                Details = JsonSerializer.Deserialize<string[]>(data.Introduction ?? "[]"),
                Desc = data.Wikipedia,
                SurfacePlot = data.ImageAddress,
                Grade = data.Grade,
                Records = count,
            };
        }



        /// <summary>
        /// 获取课程阶段
        /// </summary>
        /// <param name="courseId"></param>
        /// <returns></returns>
        public async Task<AppSrvResult<List<EduPhaseDto>>> GetEduPhase(long courseId)
        {
            return await _eduPhaseEfRepository.Where(x => x.Course == courseId && x.Deleted == false).OrderBy(x => x.Sort)
                .Select(x => new EduPhaseDto
                {
                    Id = x.Id,
                    Name = x.PhaseName
                }).ToListAsync();
        }

        public async Task<AppSrvResult> ReadingRecords(long userId, EduReadingRecordsDto input)
        {
            var exit = await _eduRecordsEfRepository.AnyAsync(x => x.User == userId && x.Course == input.Course && x.Lesson == input.Lesson);
            if (!exit)
            {
                var cource = await _eduCourseEfRepository.FindAsync(input.Course);
                if(cource == null)
                    await _eduRecordsEfRepository.InsertAsync(new EduRecords { 
                    Id = IdGenerater.GetNextId(),
                    Course = input.Course,
                    Lesson = input.Lesson,
                    User = userId,
                    CreateDate = DateTime.Now,
                    Group = cource.Group
                });
            }
            return AppSrvResult();
        }
    }
}
